iT邦幫忙

2025 iThome 鐵人賽

DAY 24
0
自我挑戰組

順著感覺走!從零開始的 Python & Vibe Coding 遊戲創作系列 第 24

第二十四天:點亮冒險世界:Pygame 遊戲視窗與背景的藝術

  • 分享至 

  • xImage
  •  

嗨,各位程式碼冒險家!歡迎來到我的「順著感覺走!從零開始的 Python & Vibe Coding 遊戲創作」第二十四天。在過去近兩週的時間裡,我們深度打造了《奇幻卡牌競技場》的核心邏輯,從 Player 類別到 GameManager,再到複雜的 AI 策略。然而,一個遊戲光有內涵是不夠的,它還需要一個引人入勝的「舞台」。

今天,我們將正式踏入遊戲的視覺化領域,探討如何利用強大的 Pygame 函式庫建立遊戲視窗、載入字體,並繪製精美的背景,為我們的奇幻世界點亮第一道光芒。這一切都將在我們的專案主入口 main.py 檔案中實現。


一、Pygame 的起點:環境初始化與資源路徑

任何 Pygame 應用程式的第一步,都是初始化其內部模組。這就像在演出開始前,確認所有燈光、音響設備都已準備就緒。

程式碼實現 (main.py)
import pygame
import sys
import os

def resource_path(relative_path):
    """取得資源的絕對路徑,不論是在開發環境還是打包後的 .exe。"""
    try:
        # PyInstaller 建立一個暫存資料夾並將路徑儲存在 _MEIPASS
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)

# 將 base_path 設為指向根目錄
base_path = resource_path(".")

# 初始化 Pygame 所有模組
pygame.init()
技術細節解析
  • pygame.init():這是啟動 Pygame 的關鍵指令。它會自動初始化所有 Pygame 需要的模組,例如圖形(display)、字體(font)和音效(mixer)等,是後續所有視覺與聽覺功能運作的基礎。
  • resource_path 函式:這個函式是確保遊戲部署流暢性的關鍵。在開發時,我們可以透過相對路徑(如 "image/background.png")找到資源。然而,當使用 PyInstaller 將遊戲打包成執行檔(.exe)時,程式的執行環境會改變,相對路徑將會失效。此函式透過檢查 sys._MEIPASS 這個 PyInstaller 在執行時才會建立的特殊屬性,來智慧地判斷當前環境,並回傳正確的資源絕對路徑,確保遊戲無論在哪種環境下都能成功載入圖片、音效等檔案。

二、搭建舞台:遊戲視窗的設計與設定

遊戲視窗是玩家與遊戲世界互動的唯一介面,其尺寸與標題是帶給玩家的第一印象。

程式碼實現 (main.py)
# 螢幕常數
SCREEN_WIDTH = 1280
SCREEN_HEIGHT = 720

# 初始化 Pygame 視窗
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("奇幻卡牌競技場")
技術細節解析
  • SCREEN_WIDTHSCREEN_HEIGHT:我們將視窗尺寸定義為常數,便於後續在程式碼中統一引用。1280x720 是一個常見的 16:9 寬螢幕解析度。
  • pygame.display.set_mode((...)):這個函式會根據傳入的元組 (寬, 高) 建立一個遊戲視窗物件,並將其賦值給 screen 變數。這個 screen 物件非常重要,它代表了主繪圖畫布,我們後續所有的繪圖操作都將在這個物件上進行。
  • pygame.display.set_caption(...):此函式用於設定視窗頂部標題列的文字,有助於提升遊戲的品牌識別度。

三、資訊的載體:中文字體的載入與應用

為了在遊戲中顯示中文提示、戰鬥日誌等資訊,我們需要載入一個支援中文的字體檔。

程式碼實現 (main.py)
# 載入中文字體
FONT_PATH = os.path.join(base_path, "msjh.ttf")
try:
    FONT_LARGE = pygame.font.Font(FONT_PATH, 28)
    FONT_MEDIUM = pygame.font.Font(FONT_PATH, 20)
    # ... 其他字體大小
except FileNotFoundError:
    print(f"Error: Font file not found... Using default system font.")
    FONT_LARGE = pygame.font.SysFont("sans-serif", 28)
    FONT_MEDIUM = pygame.font.SysFont("sans-serif", 20)
    # ...
技術細節解析
  • pygame.font.Font(font_path, size):這個函式用於從指定的字體檔案路徑(FONT_PATH)載入字體,並設定其大小(size),回傳一個字體物件。我們預先建立多個不同大小的字體物件,以便在 UI 中呈現不同層級的資訊,增加視覺層次感。
  • try-except FileNotFoundError:這是一個穩健性設計(Robustness)的體現。程式會嘗試載入 msjh.ttf 字體檔。如果檔案不存在並引發 FileNotFoundErrorexcept 區塊會被執行,程式將改用 pygame.font.SysFont 來呼叫系統預設字體。這確保了即使在缺少特定字體檔的情況下,遊戲依然可以正常顯示文字而不會崩潰,保障了流暢的使用者體驗。

四、氛圍的營造:背景圖片的繪製

背景是營造遊戲氛圍、傳達世界觀的第一印象。

程式碼實現 (main.py)
try:
    # 載入背景圖片
    background_img = pygame.image.load(os.path.join(base_path, "image", "game_background.png"))
    # 縮放圖片以符合視窗大小
    background_img = pygame.transform.scale(background_img, (SCREEN_WIDTH, SCREEN_HEIGHT))
except pygame.error:
    print("Warning: 'game_background.png' not found. Using a fallback background.")
    # 創建一個純色表面作為備用背景
    background_img = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
    background_img.fill((30, 30, 30))
技術細節解析
  • pygame.image.load(...):此函式用於從指定路徑載入一張圖片,並回傳一個 Surface 物件。
  • pygame.transform.scale(...):載入的圖片原始尺寸可能與我們的視窗大小不符。這個函式可以將圖片(background_img縮放到指定的尺寸(SCREEN_WIDTH, SCREEN_HEIGHT),確保背景能完美填充整個視窗。
  • 備用背景方案:與字體載入類似,這裡也使用了 try-except 結構。如果圖片檔 game_background.png 遺失,導致 Pygame 載入失敗,程式會建立一個純色的 pygame.Surface 物件作為備用背景。這同樣是為了防止遊戲因資源缺失而中斷,確保玩家體驗的穩定性。

透過今天的學習,我們成功地為《奇幻卡牌競技場》搭建起了堅實的視覺基礎。一個設定得當的視窗、清晰的字體以及賞心悅目的背景,是吸引玩家沉浸其中的第一步。明天,我們將在這個畫布上,繪製更多核心的視覺元素,如卡牌、UI 圖示等,讓我們的奇幻世界更加栩栩如生!


上一篇
第23天:勝負的懸念:回合推進與遊戲結束的精密判斷
下一篇
第二十五天:打造《奇幻卡牌競技場》的視覺魅力:各類遊戲元素的呈現
系列文
順著感覺走!從零開始的 Python & Vibe Coding 遊戲創作25
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言